package cn.sibu.tuchapplication;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import android.widget.Scroller;

/**
 * Created by 刘红亮 on 15-12-22 下午1:42.
 */
public class PanGestureScrollView extends FrameLayout{

    private GestureDetector mDetector;
    private Scroller mScroller;

    //最后位移事件的位置
    private float mInitialX,mInitialY;

    //拖拽阀值
    private int mTouchSlop;


    public PanGestureScrollView(Context context) {
        super(context);
        init(context);
    }

    public PanGestureScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PanGestureScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    private void init(Context context){
        mDetector = new GestureDetector(context,mListener);
        mScroller = new Scroller(context);
        //获得触摸阀值的系统常量
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    }

    /**
     * 覆写measureChild..的实现来保证生成的子视图尽可能大
     * 默认实现会强制一些子视图和该视图一样大
     */
    @Override
    protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
        Log.e("measureChild","measureChild");
        int childWidthMeasureSpec;
        int childHeightMeasureSpec;

        childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);
        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);

        child.measure(childWidthMeasureSpec,childHeightMeasureSpec);

    }

    @Override
    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
        Log.e("measureChildWithMargins","measureChildWithMargins");
        final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
        final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.leftMargin+lp.rightMargin,MeasureSpec.UNSPECIFIED);

        final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.topMargin+lp.bottomMargin,MeasureSpec.UNSPECIFIED);

        child.measure(childWidthMeasureSpec,childHeightMeasureSpec);
    }

    //处理所有触摸事件的监听器
    private GestureDetector.SimpleOnGestureListener mListener = new GestureDetector.SimpleOnGestureListener(){

        @Override
        public boolean onDown(MotionEvent e) {
            Log.e("onDown","onDown");
            //取消当前的急滑动画
            if(!mScroller.isFinished()){
                mScroller.abortAnimation();
            }
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            Log.e("onFling","onFling");
            //调用一个辅助方法来启动滚动动画
            fling((int) -velocityX / 3, (int) -velocityY/3);
            return true;
        }


        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            Log.e("onScroll","onScroll");
            //任意视图都可以调用它的scrollBy()进行滚动
            scrollBy((int) distanceX,(int) distanceY);
            return true;
        }
    };


    @Override
    public void computeScroll() {
        if(mScroller.computeScrollOffset()){
            //会在ViewGroup绘制时调用
            //我们使用这个方法保证急滑动画的顺利完成
            int oldX= getScrollX();
            int oldY = getScrollY();
            int x = mScroller.getCurrX();
            int y = mScroller.getCurrY();

            if(getChildCount()>0){
                View child = getChildAt(0);
                x = clamp(x,getWidth()-getPaddingRight()-getPaddingLeft(),child.getWidth());
                y = clamp(y,getHeight()-getPaddingBottom()-getPaddingTop(),child.getHeight());

                if(x!=oldX||y!=oldY){
                    scrollTo(x,y);
                }
            }
        }
    }

    @Override
    public void scrollTo(int x, int y) {
        //我们依赖View.scrollBy调用scrollTo
        if(getChildCount()>0){
            View child = getChildAt(0);
            x = clamp(x,getWidth() - getPaddingLeft()-getPaddingRight(),child.getWidth());
            y = clamp(y,getHeight() - getPaddingBottom()- getPaddingTop(),child.getHeight());
            if(x !=getScrollX()||y!= getScrollY()){
                super.scrollTo(x, y);
            }
        }
    }
    /**
     * 监控传递给子视图的触摸事件,并且一旦确定拖拽就进行拦截
     * */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e("onInterceptTouchEvent","onInterceptTouchEvent");
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mInitialX = ev.getX();
                mInitialY = ev.getY();
                //将按下事件传给手势检测器,这样当如果拖拽开始就有了上下文
                mDetector.onTouchEvent(ev);
            break;
            case MotionEvent.ACTION_MOVE:
                final float x = ev.getX();
                final float y = ev.getY();
                final int yDiff = (int) Math.abs(y-mInitialY);
                final int xDiff = (int) Math.abs(x-mInitialX);
                //检查x或y上的距离是否适合拖拽

                if(yDiff>mTouchSlop||xDiff>mTouchSlop){
                    //开始捕捉事件
                    return true;
                }

            break;

        }
        return super.onInterceptTouchEvent(ev);
    }

    /**
     * 将我们接受的所有触摸事件传给检测器处理
     * */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
       // Log.e("onTouchEvent","onTouchEvent");
        return mDetector.onTouchEvent(event);
    }

    //初始化scroller和开始重新绘制的实用方法
    public void fling(int velocityX,int veclocityY){

        if(getChildCount()>0){
            int height = getHeight()-getPaddingBottom()-getPaddingTop();
            int width = getWidth()-getPaddingLeft()-getPaddingRight();
            int bottom = getChildAt(0).getHeight();
            int right = getChildAt(0).getWidth();

            mScroller.fling(getScrollX(),getScrollY(),velocityX,veclocityY,0,Math.max(0, right - width),0,Math.max(0,bottom - height));
            invalidate();
        }

    }

    /**
     * 用来进行边界检查的辅助实用方法
     *
     * */
    private int clamp(int n,int my,int child){
        Log.e("clamp","my=== "+my+" n = "+n + " child = "+child);
        if(my>=child||n<0){
            //子视图超过父视图的边界或者小于父视图,不能滚动
            return 0;
        }

        if((my+n)>child){
            //请求的滚动超出了子视图的右边界
            return child - my;
        }

        return n;
    }
}
